% BEGIN LICENSE BLOCK
% Version: CMPL 1.1
%
% The contents of this file are subject to the Cisco-style Mozilla Public
% License Version 1.1 (the "License"); you may not use this file except
% in compliance with the License.  You may obtain a copy of the License
% at www.eclipse-clp.org/license.
% 
% Software distributed under the License is distributed on an "AS IS"
% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
% the License for the specific language governing rights and limitations
% under the License. 
% 
% The Original Code is  The ECLiPSe Constraint Logic Programming System. 
% The Initial Developer of the Original Code is  Cisco Systems, Inc. 
% Portions created by the Initial Developer are
% Copyright (C) 2006 Cisco Systems, Inc.  All Rights Reserved.
% 
% Contributor(s): Kish Shen, IC-Parc
% 
% END LICENSE BLOCK
%
% $Id: embtclmulti.tex,v 1.1.1.1 2006/09/23 01:49:04 snovello Exp $
%
% Author:       Kish Shen, IC-Parc
%
%----------------------------------------------------------------------
\chapter{Tcl Peer Multitasking Interface}
\label{chaptclmulti}
%HEVEA\cutdef[1]{section}
%----------------------------------------------------------------------

\section{Introduction}

This chapter describes how to use the peer multitasking interface with 
the Tcl peer interfaces. The usage is the same regardless of if the Tcl
interface is of the embedded or remote variants.

The facilities described here allows a Tcl peer to participate in peer
multitasking,  so that different peers can apparently interact with
{\eclipse} simultaneously. This would for example allow GUI windows that
are implemented using different peers for the same {\eclipse} process to be
appear as if they can interact with the host {eclipse} side at the same
time.

%----------------------------------------------------------------------
\section{Loading the interface}
%----------------------------------------------------------------------
The peer multitasking interface is provided as a Tcl-package called {\bf
eclipse_peer_multitask}, and must be loaded along with either the embedded
({\bf eclipse})  or remote ({\bf remote_eclipse}) variant of the Tcl peer
interface. 
\begin{quote}\begin{verbatim}
lappend auto_path "/location/of/my/eclipse/lib_tcl"
package require remote_eclipse
package require eclipse_peer_multitask
\end{verbatim}\end{quote}
\index{eclipse_peer_multitask (Tcl package)}

%----------------------------------------------------------------------
\section{Overview}
%----------------------------------------------------------------------
A peer must already exist before it can participate in peer multitasking:
(i.e. it has already been set up using ec_init (embedded) or ec_remote_init (remote)).

Peer multitasking occur in a {\it multitasking phase}, which is a special
way for an {\eclipse} side to hand over control to the external
side. Effectively, instead of handing over control to a single peer,
control is handed over repeatedly to all the peers that are participating
in peer multitasking. The control is shared between these peers in a
round-robin fashion, giving rise to a form of co-operative
multitasking. The multitasking is co-operative in that each peer has to
give up control, so that the control can be passed to the next multitasking
peer. A peer multitasking phase is started by calling the predicate
\bip{peer_do_multitask/1} in {\eclipse}. 


To participate in peer multitasking, a peer must be ``registered''
(initialised) for peer multitasking. This is done by executing the 
procedure {\bf ec_multi:peer_register}\index{ec_multi:peer_register (Tcl command)}
from Tcl. Once registered, the peer will take part in subsequent
multitasking phases. 


The registration can set up three user-defined handlers: the {\bf
start} handler, the {\bf interact} handler, and the {\bf end} handler.
During a multitasking phase, control is handed over to a multitasking peer,
which invokes
one of these handlers, and when the handler returns, control is handed
to the next multitasking peer. The interact handler is normally invoked,
except at the start (first) and end (last) of a multitasking phase. In
these cases, the start and end handlers are invoked respectively.

A `type' (specified in the call to \bip{peer_do_multitask/1}) is associated
with every multitasking phase to allow multitasking phases for different
purposes (distinguished by different `type's). This type is passed to the
handlers as an argument. At the start of a multitasking phase, a peer
should indicate if it is interested in this particular multitasking phase
or not. If no peer is interested in the multitasking
phase, then the multitasking phase enters the end phase after the initial
round of passing control to all the multitasking peers, i.e. control is
passed one more time to the multitasking peers, this time invoking the end
handler. If at least one peer indicates that it is interested in the
multitasking phase, then after the initial start phase, the control will be
repeatedly handed over to each multitasking peer by invoking the interact
handler. This phase is ended when one (or more) peer indicates that the
multitasking phase should end (at which point the end phase will be entered
in which the end handler will be invoked for each multitasking peer). 

\subsection{Summary of Tcl Commands}
Here is a more detailed description of the Tcl procedures:
\begin{description}
\item[\index{ec_multi:peer_register (Tcl peer multitasking)}{\bf
    ec_multi:peer_register {\it ?Multitask handlers}}] \ \\
       Registers for peer multitasking, and setup the (optional) multitask handlers.
       There handlers can be specified: a) start, invoked at the start of a
       multitasking phase; b) end, invoked at the end of a multitasking
       phase, and c) interact, invoked at other times when the peer is
       given control during a multitasking phase. {\bf Multitask handlers}
       is a list specifying the handlers, where each handler is specified
       as two list elements of the form: {\tt type name},
       where type is either {\bf start}, {\bf end} or {\bf interact}, and
       name is the name of the user defined handler. For example:
\begin{verbatim}
      ec_multi:peer_register [list interact tkecl:multi_interact_handler 
            start tkecl:multi_start_handler end tkecl:multi_end_handler]
\end{verbatim}
       When control is handed over to the peer during a peer multitasking
       phase, the appropriate handler (if defined) is invoked. When the
       handler returns, control is handed back to {\eclipse} (and passed
       to the next multitasking peer). Note 
       that events are not processed while the peer does not have control.
       The Tcl command {\bf update} is therefore called each time the peer
       is given control, to allow any accumulated events to be processed.
       As long as the peer
       is given control frequently enough, then any interactions with the
       peer would appear to be continuous.

       The handlers are invoked with the `type' of the multitasking phase
       supplied as the first  argument. This will for example allow the
       start handler to determine if it is interested in this multitasking
       phase. They can also set one of the following return codes:
\begin{description}
\item[continue] indicates that the peer wants to continue the multitasking
  phase. In  particular, this should be returned by the start handler if it is
  interested in the multitasking phase. Note that the multitasking phase is
  not guaranteed to continue, as it can be terminated by another
  multitasking peer.
\item[terminate] indicates the termination of a multitasking phase. The
  multitasking phase will enter the end phase, where the end handlers
  will be invoked once per peer before the multitasking phase finishes.
\end{description}
       For example, here is the start handler used in the Tk development
       tools:
\begin{verbatim}
proc tkecl:multi_start_handler {type} {

    switch $type {
        tracer {
            # multitasking phase is `tracer'
            # only do handling of port if the tracer window exists
            if [winfo exists .ec_tools.ec_tracer] {
                tkecl:handle_tracer_port_start
                set of_interest  continue
            }
        }
        default {
            set of_interest no
            # do nothing
        }
    }

    return $of_interest
}

\end{verbatim}

An error is raised if this procedure is called while the peer is already
registered for multitasking.

\item[\index{ec_multi:peer_deregister (Tcl peer multitasking)}{\bf
    ec_multi:peer_deregister}] \ \\
      Deregisters peer from multitasking. After calling this procedure, the
      peer will not participate in any further multitasking. If this
      procedure is called during a multitasking phase, the peer will not
      participate further in that multitasking phase once control is
      returned. The multitasking phase will continue, unless there are no
      multitasking peers left, in which case an error will be raised on the 
      {\eclipse} side. The peer multitask control queue will be
      automatically closed.

      An error is raised if this procedure is called while the peer is
      not registered for multitasking.

\item[\index{ec_multi:get_multi_status (Tcl peer multitasking)}{\bf
    ec_multi:get_multi_status}] \ \\
      Returns the current peer multitasking status for the peer. The values
    can be:
\begin{itemize}
\item not_registered: the peer is not registered for peer multitasking.
\item off: the peer is registered for peer multitasking, but is not
  currently in a multitasking phase.
\item on: the peer is registered for peer multitasking, and is currently in
  a multitasking phase.
\end{itemize}

Note that the peer multitasking code is implemented using peer queue
handlers. Thus, the peer multitask status is set to `on'  
before the multitask start handler is called, but {\it after\/} the
`{\eclipse} end' handler.
%%% Kish, this didn't seem to make any sense:
% invoked when control is being handed to the peer (as set up in {\bf
%  ec_running_set_commands}.
Conversely, the peer multitask status is set to
`off' after the multitask end handler, but {\it before\/} the {\eclipse}
start handler.
\end{description}

\section{Example}

Here we present a simple example use of the Tcl peer multitasking
facilities. The full programs (Tcl and {\eclipse} code) are available in
the {\eclipse} distribution as {\tt example_multi.ecl} and {\tt
  example_multi.tcl}.


The Tcl program uses the remote Tcl peer interface to create a window that
interacts with the {\eclipse} process it is attached to. Multiple copies of
the program can be run, and attached to the same {\eclipse} process with a
different remote peer. Each window has three buttons:
\begin{itemize}
\item run: a button to send an ERPC goal to {\eclipse} (in this case a simple
  writeln with the peer name;
\item end: a button to end interaction with {\eclipse} and return control
  to {\eclipse};
\item reg: a button to toggle the registration/deregistration of the peer
  for peer multitasking;
\end{itemize}

The program interacts with {\eclipse} when the run button is pressed. This
can be done either during a peer multitasking phase, or when the program's specific
peer is given control on its own. When the peer is given control on its
own, only it can interact with {\eclipse}; while during peer multitasking,
all the multitasking peers (the copies of the program that are running) can
interact with {\eclipse}, i.e.\ the run buttons in all the windows can all
be pressed. 

After attaching to {\eclipse} with {\bf ec_remote_init}, the program sets
various handlers for the handing of control between {\eclipse} and itself
with {\bf ec_running_set_commands}: 

\begin{verbatim}

ec_running_set_commands ec_start ec_end {} disable_buttons

\end{verbatim}

The handlers for when control is handed back to {\eclipse}, {\tt ec_start},
and when control is handed over from {\eclipse}, {\tt ec_end}, are defined
thus: 

\begin{verbatim}

proc ec_end {} {
    if {[ec_multi:get_multi_status] != "on"} {
        enable_buttons
    }
}

proc ec_start {} {
    if {[ec_multi:get_multi_status] != "on"} {
        disable_buttons
    }
}

\end{verbatim}

{\tt enable_buttons} and {\tt disable_buttons} enables and disables the
buttons for the window, respectively. The code tests if the peer is
multitasking with {\tt ec_multi:get_multi_status}. This is needed because
during a peer multitasking phase, control is repeatedly handed back and
forth, and we don't want the buttons to be repeatedly enabled and disabled
during this phase.

Next, the program registers the peer for peer multitasking:

\begin{verbatim}

    ec_multi:peer_register [list start multi_start_handler \
                            interact multi_interact_handler]

\end{verbatim}

No special handler is
needed for the end of multitasking, as no special action is needed beyond
disabling the buttons. The return code is stored in a global variable {\tt
  return_code}. The start handler is defined thus:

\begin{verbatim}
proc multi_start_handler {type} {
    global return_code

    if {$type == "demo"} {
        set return_code continue
        enable_buttons
    } else {
        set return_code no
    }
    return $return_code
}
\end{verbatim}

As discussed, multitasking phases can be of different types. For
demonstrating this multitasking features of this example program, the type
is ``demo''. Therefore the handler tests for this and enables the button if
the phase is ``demo''. On the {\eclipse} side, the multitasking phase is
started with the following predicate call:

\begin{verbatim}
        peer_do_multitask(demo),
\end{verbatim}

The interact handler is defined thus:

\begin{verbatim}
proc multi_interact_handler {type} {
    global return_code

    if {$return_code == "terminate"} {
            disable_buttons
    }
    return $return_code
\end{verbatim}

The code checks for the two cases where the user has requested to terminate
the multitasking phase by pressing the {\tt .end} button, and disables the
buttons. The end button itself invokes the following code to set {\tt
  return_code}: 


\begin{verbatim}
proc end_interaction {} {
    global return_code
    set return_code terminate
    if {[ec_multi:get_multi_status] != "on"} {
        ec_resume
    }
}
\end{verbatim}

The code checks if it is in a peer multitasking phase, and if so,
{\tt return_code} is set to {\tt terminate}, so that when the handler
returns, the multitasking phase will terminate.
Otherwise, the peer has been explicitly handed control exclusively,
and so control is handed back to {\eclipse} in the normal way using {\bf
  ec_resume}.

The program also allows a peer to deregister from multitasking or, if
already deregistered, to register again for multitasking. This is handling
by the following two procedures:

\begin{verbatim}
proc register_for_multi {} {
    ec_multi:peer_register [list start multi_start_handler]
    .reg configure  -command {deregister_for_multi}
    .reg configure -text "Deregister multitasking"
}

proc deregister_for_multi {} {
    ec_multi:peer_deregister
    .reg configure  -command {register_for_multi}
    .reg configure -text "Register multitasking"
}
\end{verbatim}

\noindent
Pressing the {\tt .reg} button will either call {\tt register_for_multi} or
{\tt deregister_for_multi}, depending on if the peer is currently
deregistered or registered for peer multitasking (respectively). The
procedure also changes the button to toggle to the other state.

Pressing the button during a peer multitasking phase will remove the peer
from multitasking immediately. If pressed while the peer is given exclusive
control, the peer will not participate in future multitasking phase (unless
it is re-registered). 

%HEVEA\cutend

 